//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CXmlNodeData.cpp>
///	@path	~/src/database/xdata/
///	@date	2007/12/03
///	@desc	XML type node entry.

#include "config/config.h"

#include "database/xdata/CXmlNodeData.h"

namespace xeres {
	
	IMPL_IOBJECT_CLASS( CXmlNodeData );

	// CXmlNodeData
	CXmlNodeData::CXmlNodeData( const Key& name )
		: m_key( name )
	{
	}

	// ~CXmlNodeData
	CXmlNodeData::~CXmlNodeData( void )
	{

	}

	// GetInfo
	bool CXmlNodeData::GetInfo( DataInfo& datainfo )
	{
		datainfo.m_type = DATA_NODE;
		datainfo.m_size = 0;
		datainfo.m_created = 0;
		datainfo.m_accessed = 0;
		datainfo.m_modified = 0;
		return true;
	}

	// GetVarTypeName
	const WString& CXmlNodeData::GetVarTypeName( void ) const
	{
		return m_data.GetVarTypeName();
	}

	// GetVarTypeID
	const ClassID CXmlNodeData::GetVarTypeID( void ) const
	{
		return m_data.GetVarTypeID();
	}

	// SetBool
	bool CXmlNodeData::SetBool( bool val )
	{
		return m_data.SetBool( val );
	}

	// SetInt
	bool CXmlNodeData::SetInt( int val )
	{
		return m_data.SetInt( val );
	}

	// SetFloat
	bool CXmlNodeData::SetFloat( float val )
	{
		return m_data.SetFloat( val );
	}

	// SetPair
	bool CXmlNodeData::SetPair( const Pair<float>& val )
	{
		return m_data.SetPair( val );
	}

	// SetVector
	bool CXmlNodeData::SetVector( const Vector<float>& val )
	{
		return m_data.SetVector( val );
	}

	// SetQuat
	bool CXmlNodeData::SetQuat( const Quat<float>& val )
	{
		return m_data.SetQuat( val );
	}

	// SetColor
	bool CXmlNodeData::SetColor( const Color4& val )
	{
		return m_data.SetColor( val );
	}

	// SetMatrix
	bool CXmlNodeData::SetMatrix( const Matrix<float>& val )
	{
		return m_data.SetMatrix( val );
	}

	// SetString
	bool CXmlNodeData::SetString( const WString& val )
	{
		return m_data.SetString( val );
	}

	// GetBool
	bool CXmlNodeData::GetBool( bool& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			if( _wcsicmp( _S("true") , str.c_str() ) == 0 )
				val = true;
			else if( _wcsicmp( _S("false") , str.c_str() ) == 0 )
				val = false;
			else
				return false;
			return true;
		}
		return m_data.GetBool( val );
	}

	// GetInt
	bool CXmlNodeData::GetInt( int& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%d") , &val ) == 1 );
		}
		return m_data.GetInt( val );
	}

	// GetFloat
	bool CXmlNodeData::GetFloat( float& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f") , &val ) == 1 );
		}
		return m_data.GetFloat( val );
	}

	// GetPair
	bool CXmlNodeData::GetPair( Pair<float>& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f , %f") , &val.x , &val.y ) == 2 );
		}
		return m_data.GetPair( val );
	}

	// GetVector
	bool CXmlNodeData::GetVector( Vector<float>& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f , %f , %f") , &val.x , &val.y , &val.z ) == 3 );
		}
		return m_data.GetVector( val );
	}

	// GetQuat
	bool CXmlNodeData::GetQuat( Quat<float>& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f , %f , %f , %f") , &val.real , &val.x , &val.y , &val.z ) == 4 );
		}
		return m_data.GetQuat( val );
	}

	// GetColor
	bool CXmlNodeData::GetColor( Color4& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f , %f , %f , %f") , &val.r , &val.g , &val.b , &val.a ) == 4 );
		}
		return m_data.GetColor( val );
	}

	// GetMatrix
	bool CXmlNodeData::GetMatrix( Matrix<float>& val ) const
	{
		if( m_data.GetVaryingDataType() == VAR_STRING )
		{
			WString str;
			XS_VERIFY( m_data.GetString( str ) );
			return ( swscanf( str.c_str() , _S("%f , %f , %f , %f | %f , %f , %f , %f | %f , %f , %f , %f | %f , %f , %f , %f") ,
				val.m16[0] , val.m16[1] , val.m16[2] , val.m16[3] , 
				val.m16[4] , val.m16[5] , val.m16[6] , val.m16[7] , 
				val.m16[8] , val.m16[9] , val.m16[10] , val.m16[11] , 
				val.m16[12] , val.m16[13] , val.m16[14] , val.m16[15] ) == 16 );
		}
		return m_data.GetMatrix( val );
	}

	// GetString
	bool CXmlNodeData::GetString( WString& val ) const
	{
		return m_data.GetString( val );
	}

	// GetKey
	const Key& CXmlNodeData::GetKey( void ) const
	{
		return m_key;
	}

	// GetAttribute
	bool CXmlNodeData::GetAttribute( const WString& attr , WString& value , const WString& defaultVal )
	{
		dict<WString,WString>::iterator it = m_attrs.find( attr );
		if( it == m_attrs.end() )
		{
			value = defaultVal;
			return false;
		}
		else
		{
			value = it->second;
			return true;
		}
	}

	// SetAttribute
	bool CXmlNodeData::SetAttribute( const WString& attr , const WString& value )
	{
		m_attrs[attr] = value;
		return true;
	}

	// GetAttributeCount
	size_t CXmlNodeData::GetAttributeCount( void )
	{
		return m_attrs.size();
	}

	// AttributeBegin
	void * CXmlNodeData::AttributeBegin( void )
	{
		return new dict<WString,WString>::iterator( m_attrs.begin() );
	}

	// AttributeIterate
	bool CXmlNodeData::AttributeIterate( void * context , WString& name , WString& value , bool iterateNext )
	{
		dict<WString,WString>::iterator& it = *(dict<WString,WString>::iterator*)context;
		if( it == m_attrs.end() )
			return false;
		name = it->first;
		value = it->second;
		if( iterateNext )
			++it;
		return true;
	}

	// AttributeEnd
	void CXmlNodeData::AttributeEnd( void * context )
	{
		delete (dict<WString,WString>::iterator*)context;
	}

	// NewChild
	RefPass<IData> CXmlNodeData::NewChild( const Key& key )
	{
		// introduce child maker
		RefPass<CXmlNodeData> child = new CXmlNodeData( key );
		m_children.push_back( RefWeak<IData>( child ) );
		return child;
	}

	// GetChildCount
	size_t CXmlNodeData::GetChildCount( void )
	{
		return m_children.size();
	}

	// GetChild
	RefPass<IData> CXmlNodeData::GetChild( const Key& key )
	{
		for( size_t i = 0 , total = m_children.size() ; i < total ; ++i )
		{
			if( m_children[i]->GetKey() == key )
			{
				return m_children[i];
			}
		}
		return NULL;
	}

	// GetChild
	RefPass<IData> CXmlNodeData::GetChild( size_t index )
	{
		if( index >= m_children.size () )
		{
			return NULL;
		}
		return m_children[index];
	}

	// GetChildInfo
	bool CXmlNodeData::GetChildInfo( const Key& key , DataInfo& info )
	{
		for( size_t i = 0 , total = m_children.size() ; i < total ; ++i )
		{
			if( m_children[i]->GetKey() == key )
			{
				return m_children[i]->GetInfo( info );
			}
		}
		return false;
	}

	// GetChildInfo
	bool CXmlNodeData::GetChildInfo( size_t index , DataInfo& info , WString& name )
	{
		if( index >= m_children.size() )
		{
			TRACE_ERROR( _S("CTreeEntry::GetChildInfo: Index out of children range.") );
			return false;
		}
		name = m_children[index]->GetKey().GetCStr();
		return m_children[index]->GetInfo( info );
	}

	// FindChildIndex
	bool CXmlNodeData::FindChildIndex( const Key& key , size_t& index )
	{
		// first we find all directories
		for( size_t i = index , total = m_children.size() ; i < total ; ++i , ++index )
		{
			if( m_children[i]->GetKey() == key )
				return true;
		}
		index = npos;
		return false;
	}

	// FindChild
	RefPass<IData> CXmlNodeData::FindChild( const Key& key , size_t& index )
	{
		// first we find all directories
		for( size_t i = index , total = m_children.size() ; i < total ; ++i )
		{
			++index;
			if( m_children[i]->GetKey() == key )
				return m_children[i];
		}
		index = npos;
		return NULL;
	}

	// Save
	bool CXmlNodeData::Save( void )
	{
		return false;
	}

	// Reload
	bool CXmlNodeData::Reload( void )
	{
		return false;
	}

} // namespace xeres
